package magnet.processor.instances.aspects.selector;

import com.squareup.javapoet.*;
import magnet.processor.instances.GetSelectorMethod;
import magnet.processor.instances.generator.AspectGenerator;

import javax.lang.model.element.Modifier;

public class GetSelectorMethodGenerator implements AspectGenerator {

    private MethodSpec methodSpec = null;
    private FieldSpec constantFieldSpec = null;
    private CodeBlock.Builder constantInitializer = null;
    private int argumentsLeft = 0;

    @Override
    public void generate(TypeSpec.Builder classBuilder) {
        if (constantFieldSpec != null) {
            classBuilder.addField(constantFieldSpec);
        }
        if (methodSpec != null) {
            classBuilder.addMethod(methodSpec);
        }
    }

    @Override
    public void reset() {
        methodSpec = null;
        constantFieldSpec = null;
        constantInitializer = null;
        argumentsLeft = 0;
    }

    public void enterGetSelectorMethod(GetSelectorMethod method) {
        methodSpec = MethodSpec
                .methodBuilder("getSelector")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(Override.class)
            .returns(ArrayTypeName.of(String.class))
            .addStatement("return SELECTOR")
                .build();
        constantInitializer = CodeBlock.builder().add("{ ");
        argumentsLeft = method.getSelectorArguments().size();
    }

    public void visitSelectorArgument(String argument) {
        if (--argumentsLeft > 0) {
            checkNotNull(constantInitializer).add("$S, ", argument);
        } else {
            checkNotNull(constantInitializer).add("$S }", argument);
        }
    }

    public void exitGetSelectorMethod() {
        constantFieldSpec = FieldSpec
                .builder(ArrayTypeName.of(String.class), "SELECTOR")
                .addModifiers(Modifier.PRIVATE, Modifier.STATIC)
                .initializer(checkNotNull(constantInitializer).build())
                .build();
    }

    private <T> T checkNotNull(T value) {
        if (value == null) {
            throw new IllegalArgumentException("Required value was null.");
        }
        return value;
    }
}
